home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / uupc11ys.zip / LIB / SECURITY.C < prev    next >
C/C++ Source or Header  |  1993-04-10  |  34KB  |  859 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    s e c u r i t y . c                                             */
  3. /*                                                                    */
  4. /*    Security routines for UUPC/extended                             */
  5. /*                                                                    */
  6. /*    Copyright (c) 1991, Andrew H. Derbyshire                        */
  7. /*    See README.PRN for additional copyrights and restrictions       */
  8. /*--------------------------------------------------------------------*/
  9.  
  10. /*--------------------------------------------------------------------*/
  11. /*                          RCS Information                           */
  12. /*--------------------------------------------------------------------*/
  13.  
  14. /*
  15.  *    $Id: SECURITY.C 1.5 1993/04/11 00:31:04 ahd Exp $
  16.  *
  17.  *    Revision history:
  18.  *    $Log: SECURITY.C $
  19.  *     Revision 1.5  1993/04/11  00:31:04  ahd
  20.  *     Global edits for year, TEXT, etc.
  21.  *
  22.  *     Revision 1.4  1993/03/06  22:48:23  ahd
  23.  *     Re-do compare of sort to void bug in some qsort() functions
  24.  *
  25.  * Revision 1.3  1992/11/22  20:58:55  ahd
  26.  * Normalize directories as read
  27.  * Use strpool to allocate const strings
  28.  *
  29.  * Revision 1.2  1992/11/19  02:57:31  ahd
  30.  * drop rcsid
  31.  *
  32.  * Revision 1.1  1992/11/16  05:00:26  ahd
  33.  * Initial revision
  34.  *
  35.  */
  36.  
  37. /*--------------------------------------------------------------------*/
  38. /*                        System include files                        */
  39. /*--------------------------------------------------------------------*/
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <ctype.h>
  44. #include <string.h>
  45. #include <sys/types.h>        /* Only really needed for MS C         */
  46. #include <sys/stat.h>
  47. #include <time.h>
  48. #include <direct.h>
  49.  
  50. /*--------------------------------------------------------------------*/
  51. /*                    UUPC/extended include files                     */
  52. /*--------------------------------------------------------------------*/
  53.  
  54. #include "lib.h"
  55. #include "hostable.h"
  56. #include "security.h"
  57. #include "usertabl.h"
  58. #include "expath.h"
  59. #include "hlib.h"
  60.  
  61. /*--------------------------------------------------------------------*/
  62. /*                           Local defines                            */
  63. /*--------------------------------------------------------------------*/
  64.  
  65. static boolean InitEntry( char *buf, const char *fname);
  66.  
  67. static size_t InitDir( char *directories,
  68.          const REMOTE_ACCESS access,
  69.          const boolean grant,
  70.          struct HostSecurity *anchor,
  71.          size_t max_elements );
  72.  
  73. int dircmp( const void *a , const void *b );
  74.  
  75. /*--------------------------------------------------------------------*/
  76. /*                          Global varables                           */
  77. /*--------------------------------------------------------------------*/
  78.  
  79. struct HostSecurity *securep = NULL;
  80. static struct HostSecurity *default_security = NULL;
  81. static char drive[] = "C:";
  82.  
  83. currentfile();
  84.  
  85. /*--------------------------------------------------------------------*/
  86. /*    L o a d S e c u r i t y                                         */
  87. /*                                                                    */
  88. /*    Initialize security processing; returns TRUE if security        */
  89. /*    initialized, otherewise FALSE                                   */
  90. /*--------------------------------------------------------------------*/
  91.  
  92. boolean LoadSecurity( void )
  93. {
  94.    char fname[FILENAME_MAX];
  95.    char buffer[BUFSIZ*4];     /* Allows around 2K for the data       */
  96.    struct HostTable *hostp;
  97.    FILE *stream;
  98.  
  99. /*--------------------------------------------------------------------*/
  100. /*      Generate a filename for the permissions file and open it      */
  101. /*--------------------------------------------------------------------*/
  102.  
  103.    mkfilename(fname, E_confdir, PERMISSIONS);
  104.    stream  = FOPEN( fname, "r",TEXT_MODE);
  105.  
  106.    if ( stream == NULL )      /* Did the file open?                  */
  107.    {                          /* No --> Report failure to caller     */
  108.       printerr( fname );
  109.       return FALSE;
  110.    } /* ( stream == NULL ) */
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*              Get current drive for normalizing names               */
  114. /*--------------------------------------------------------------------*/
  115.  
  116.    getcwd( buffer, sizeof buffer );
  117.    *drive = *buffer;
  118.  
  119. /*--------------------------------------------------------------------*/
  120. /*               Begin processing the PERMISSIONS file                */
  121. /*--------------------------------------------------------------------*/
  122.  
  123.    while ( !feof( stream ) )
  124.    {
  125.       char *next = buffer;
  126.  
  127. /*--------------------------------------------------------------------*/
  128. /*                Build up the buffer to be processed                 */
  129. /*--------------------------------------------------------------------*/
  130.  
  131.       *next = '\0';
  132.       while( fgets( next, sizeof buffer - strlen(next), stream ) != NULL)
  133.       {
  134.          if ((*next == '#') || (*next == '\n'))
  135.          {
  136.             *next = '\0';
  137.             continue;
  138.          }
  139.  
  140.          next = next + strlen( next ) - 1;
  141.          if (*next == '\n')
  142.             *next-- = '\0';
  143.          else if (!feof( stream ))  /* Did we hit EOF?               */
  144.          {                    /* No --> Presume the buffer overflowed*/
  145.             printmsg(0,"LoadSecurity: buffer overflow while reading %s",
  146.              fname);
  147.             fclose( stream );
  148.             return FALSE;
  149.          }
  150.  
  151.          while( isspace( *next ))   /* Dump trailing white space     */
  152.             *next-- = '\0';
  153.  
  154.          if (*next == '\\')
  155.             *next = '\0';
  156.          else
  157.             break;
  158.       } /* while( fgets( next, sizeof available, stream )) != NULL)) */
  159.  
  160. /*--------------------------------------------------------------------*/
  161. /*            Done read the data; verify we had no errors             */
  162. /*--------------------------------------------------------------------*/
  163.  
  164.       if (ferror( stream ))
  165.       {
  166.          printerr( fname );
  167.          clearerr( stream );
  168.          return FALSE;
  169.       } /* if */
  170.  
  171. /*--------------------------------------------------------------------*/
  172. /*              Build entries for one permissions entry               */
  173. /*--------------------------------------------------------------------*/
  174.  
  175.       printmsg(10,"Buffer is \"%s\"", buffer );
  176.       if ((*next != '\0') && !InitEntry( buffer , fname))
  177.       {
  178.          fclose( stream );
  179.          return FALSE;
  180.       }
  181.  
  182.    } /* while ( !feof( stream ) ) */
  183.  
  184. /*--------------------------------------------------------------------*/
  185. /*                    Initialize local host entry                     */
  186. /*--------------------------------------------------------------------*/
  187.  
  188.    hostp = checkname( E_nodename );
  189.    if ( hostp == NULL )
  190.       panic();
  191.    hostp->hsecure = malloc( sizeof *hostp->hsecure );
  192.    checkref( hostp->hsecure );
  193.    memset( hostp->hsecure , '\0', sizeof *hostp->hsecure);
  194.                               /* Clear pointers                      */
  195.    hostp->hsecure->local = TRUE;
  196.  
  197. /*--------------------------------------------------------------------*/
  198. /*                          Return to caller                          */
  199. /*--------------------------------------------------------------------*/
  200.  
  201.    fclose( stream );
  202.    return TRUE;
  203.  
  204. } /* LoadSecurity */
  205.  
  206. /*--------------------------------------------------------------------*/
  207. /*    I n i t i a l i z e E n t r y                                   */
  208. /*                                                                    */
  209. /*    Initialize a single permissions file entry                      */
  210. /*--------------------------------------------------------------------*/
  211.  
  212. static boolean InitEntry( char *buf, const char *fname)
  213. {
  214.  
  215. /*--------------------------------------------------------------------*/
  216. /*                      Configuration variables                       */
  217. /*--------------------------------------------------------------------*/
  218.  
  219.   static char *myname, *validate, *commands;
  220.  
  221.   static char *callback, *xpubdir, *machine, *noread, *nowrite;
  222.   static char *request, *read, *sendfiles,  *write, *logname;
  223.  
  224.   static CONFIGTABLE securetable[] = {
  225.      { "callback",      &callback,     B_TOKEN  | B_UUXQT } ,
  226.      { "commands",      &commands,     B_CLIST  | B_UUXQT } ,
  227.      { "logname",       &logname,      B_TOKEN  | B_UUXQT } ,
  228.      { "machine",       &machine,      B_TOKEN  | B_UUXQT | B_MALLOC } ,
  229.      { "myname",        &myname,       B_TOKEN  | B_UUXQT } ,
  230.      { "pubdir",        &xpubdir,      B_PATH   | B_UUXQT } ,
  231.      { "noread",        &noread,       B_TOKEN  | B_UUXQT | B_MALLOC } ,
  232.      { "nowrite",       &nowrite,      B_TOKEN  | B_UUXQT | B_MALLOC } ,
  233.      { "read",          &read,         B_TOKEN  | B_UUXQT | B_MALLOC} ,
  234.      { "request",       &request,      B_TOKEN  | B_UUXQT } ,
  235.      { "sendfiles",     &sendfiles,    B_TOKEN  | B_UUXQT } ,
  236.      { "validate",      &validate,     B_CLIST  | B_UUXQT } ,
  237.      { "write",         &write,        B_TOKEN  | B_UUXQT | B_MALLOC } ,
  238.      { nil(char) }
  239. }; /* securetable */
  240.  
  241.    struct HostSecurity *anchor = malloc( sizeof *anchor );
  242.  
  243. /*--------------------------------------------------------------------*/
  244. /*                  Default list of allowed commands                  */
  245. /*--------------------------------------------------------------------*/
  246.  
  247.    static char *command_list[] = { "rmail", "rnews" , NULL } ;
  248.  
  249. /*--------------------------------------------------------------------*/
  250. /*                          Other variables                           */
  251. /*--------------------------------------------------------------------*/
  252.  
  253.    boolean success = TRUE;
  254.    CONFIGTABLE *tptr;
  255.    char *token = buf;
  256.    char *parameter;
  257.    struct UserTable *userp;
  258.    struct HostTable *hostp;
  259.    size_t max_elements = 16;
  260.  
  261. /*--------------------------------------------------------------------*/
  262. /*                 Initialize the security structure                  */
  263. /*--------------------------------------------------------------------*/
  264.  
  265.    checkref( anchor );
  266.    memset( anchor , '\0', sizeof *anchor); /* Clear pointers         */
  267.  
  268. /*--------------------------------------------------------------------*/
  269. /*                        Initialize the table                        */
  270. /*--------------------------------------------------------------------*/
  271.  
  272.    for (tptr = securetable; tptr->sym != nil(char); tptr++)
  273.       if (tptr->bits & (B_TOKEN | B_STRING | B_LIST| B_CLIST))
  274.          *(tptr->loc) = nil(char);
  275.  
  276. /*--------------------------------------------------------------------*/
  277. /*                 Parse the information in the table                 */
  278. /*--------------------------------------------------------------------*/
  279.  
  280.    while ( (parameter = strtok( token, WHITESPACE )) != NULL)
  281.    {
  282.       token = strtok( NULL, ""); /* Save for next pass               */
  283. #ifdef _DEBUG
  284.       printmsg(8,"InitEntry: Parameter is \"%s\"", parameter);
  285.       if ( token != NULL )
  286.          printmsg(10,"InitEntry: Buffer remaining is \"%s\"", token);
  287. #endif
  288.       if (!processconfig(parameter, SYSTEM_CONFIG,B_UUXQT,securetable,NULL))
  289.       {
  290.          printmsg(0,
  291.           "Unknown keyword \"%s\" in %s ignored",parameter, fname);
  292.          success = FALSE;
  293.       } /* if */
  294.    } /* while ( (parameter = strtok( token, WHITESPACE )) != NULL) */
  295.  
  296.    anchor->commands = (char **) commands;
  297.    anchor->validate = (char **) validate;
  298.  
  299. /*--------------------------------------------------------------------*/
  300. /*    Now we have the data procesed by keyword, break it down more    */
  301. /*--------------------------------------------------------------------*/
  302.  
  303.    if ((logname == NULL) && (machine == NULL))
  304.    {
  305.       printmsg(0,"InitEntry: No machine or logname given in %s",
  306.                   fname );
  307.       success = FALSE;
  308.    } /* if ((logname == NULL) && (machine == NULL)) */
  309.  
  310. /*--------------------------------------------------------------------*/
  311. /*                        Handle a login name                         */
  312. /*--------------------------------------------------------------------*/
  313.  
  314.    if (logname != NULL)
  315.    {
  316.       printmsg(10,"InitEntry: Processing logname=%s",logname );
  317.       userp = checkuser( logname );
  318.       if ( userp == BADUSER )
  319.       {
  320.          printmsg(0,"InitEntry: Invalid user id in %s, LOGNAME=%s",
  321.                      fname, logname );
  322.          success = FALSE;
  323.       } /* if ( userp == BADUSER ) */
  324.       else if (userp->hsecure == NULL)
  325.          userp->hsecure = anchor;
  326.       else {
  327.          printmsg(0,"InitEntry: Duplicate user id in %s, LOGNAME=%s",
  328.                      fname, logname );
  329.          success = FALSE;
  330.       } /* else */
  331.    } /* if (logname != NULL) */
  332.  
  333. /*--------------------------------------------------------------------*/
  334. /*                        Handle machine names                        */
  335. /*--------------------------------------------------------------------*/
  336.  
  337.    token = machine;
  338.    while( token != NULL )
  339.    {
  340.       char *host = strtok( token, ":");
  341.       printmsg(10,"InitEntry: Processing machine=%s", host );
  342.  
  343.       token = strtok( NULL, "");
  344.       if ( equal( host , ANY_HOST ) )
  345.       {
  346.          if ( default_security == NULL )
  347.             default_security = anchor;
  348.          else {
  349.             printmsg(0,"InitEntry: "
  350.                        "Multiple MACHINE entries in %s which specify OTHER",
  351.                        fname);
  352.             success = FALSE;
  353.          } /* else */
  354.       } /* if ( equal( host , ANY_HOST ) ) */
  355.       else {
  356.          hostp = checkreal( host );
  357.          if ( hostp == BADUSER )
  358.          {
  359.             printmsg(0,"InitEntry: Invalid host id in %s, MACHINE=%s",
  360.                         fname, host );
  361.             success = FALSE;
  362.          } /* if ( hostp == BADUSER ) */
  363.          else if (hostp->hsecure == NULL)
  364.             hostp->hsecure = anchor;
  365.          else {
  366.             printmsg(0,"InitEntry: Duplicate host id in %s, MACHINE=%s",
  367.                         fname, token );
  368.             success = FALSE;
  369.          } /* else */
  370.       } /* else */
  371.    } /* while( token != NULL ) */
  372.  
  373.    if ( machine != NULL )
  374.       free( machine );
  375.  
  376. /*--------------------------------------------------------------------*/
  377. /*                       Handle validated names                       */
  378. /*--------------------------------------------------------------------*/
  379.  
  380.    if ( anchor->validate != NULL )
  381.    {
  382.       char **plist = anchor->validate;
  383.  
  384.       while ( *plist != NULL )
  385.       {
  386.          hostp = checkreal( *plist );
  387.  
  388.          if ( hostp == BADUSER )
  389.          {
  390.             printmsg(0,"InitEntry: Invalid host id in %s, VALIDATE=%s",
  391.                         fname, *plist);
  392.             success = FALSE;
  393.          } /* if ( hostp == BADUSER ) */
  394.          else
  395.             hostp->anylogin = FALSE;   /* Flag we must use specific
  396.                                           login                      */
  397.  
  398.          plist++;             /* Step to next hostname in list       */
  399.  
  400.       } /* while ( *plist != NULL ) */
  401.  
  402.    } /* if ( anchor->validate != NULL ) */
  403.  
  404. /*--------------------------------------------------------------------*/
  405. /*                          Handle CALLBACK                           */
  406. /*--------------------------------------------------------------------*/
  407.  
  408.    if ( callback != NULL )
  409.    {
  410.       if (equal(strlwr(callback),"no"))
  411.          anchor->callback = FALSE;
  412.       else if (equal(callback,"yes"))
  413.          anchor->callback = TRUE;
  414.       else {
  415.          printmsg(0,"InitEntry: Invalid value in %s, CALLBACK=%s",
  416.                      fname, callback );
  417.          success = FALSE;
  418.       } /* else */
  419.    } /* if ( callback != NULL ) */
  420.  
  421. /*--------------------------------------------------------------------*/
  422. /*                          Handle REQUEST                            */
  423. /*--------------------------------------------------------------------*/
  424.  
  425.    if ( request != NULL )
  426.    {
  427.       if (equal(strlwr(request),"no"))
  428.          anchor->request = FALSE;
  429.       else if (equal(request,"yes"))
  430.          anchor->request = TRUE;
  431.       else {
  432.          printmsg(0,"InitEntry: Invalid value in %s, REQUEST=%s",
  433.                      fname, request );
  434.          success = FALSE;
  435.       } /* else */
  436.  
  437.    } /* if ( request != NULL ) */
  438.  
  439. /*--------------------------------------------------------------------*/
  440. /*                          Handle SENDFILES                          */
  441. /*--------------------------------------------------------------------*/
  442.  
  443.    if ( sendfiles != NULL)
  444.    {
  445.       if (equal(strlwr(sendfiles),"call"))
  446.          anchor->sendfiles = FALSE;
  447.       else if (equal(sendfiles,"yes"))
  448.          anchor->sendfiles = TRUE;
  449.       else {
  450.          printmsg(0,"InitEntry: Invalid value in %s, SENDFILES=%s",
  451.                      fname, sendfiles );
  452.          success = FALSE;
  453.       } /* else */
  454.    } /* if */
  455.  
  456. /*--------------------------------------------------------------------*/
  457. /*                          handle commands                           */
  458. /*--------------------------------------------------------------------*/
  459.  
  460.    if ( anchor->commands == NULL )
  461.       anchor->commands = command_list;
  462.  
  463. /*--------------------------------------------------------------------*/
  464. /*                 Handle local system name aliasing                  */
  465. /*--------------------------------------------------------------------*/
  466.  
  467.    if (myname == NULL)
  468.       anchor->myname = E_nodename;
  469.    else
  470.       anchor->myname = myname;
  471.  
  472. /*--------------------------------------------------------------------*/
  473. /*                      Directory processing                          */
  474. /*--------------------------------------------------------------------*/
  475.  
  476.    anchor->dirlist = malloc( sizeof anchor->dirlist[0] * max_elements );
  477.    checkref( anchor->dirlist );
  478.  
  479.    max_elements = InitDir( read,    ALLOW_READ,  TRUE,  anchor,
  480.             max_elements );
  481.    free( read );
  482.    max_elements = InitDir( noread,  ALLOW_READ,  FALSE, anchor,
  483.             max_elements );
  484.    free( noread );
  485.    max_elements = InitDir( write,   ALLOW_WRITE, TRUE,  anchor,
  486.             max_elements );
  487.    free( write );
  488.    max_elements = InitDir( nowrite, ALLOW_WRITE, FALSE, anchor,
  489.                            max_elements );
  490.    free( nowrite );
  491.  
  492. /*--------------------------------------------------------------------*/
  493. /*                 Provide a default public directory                 */
  494. /*--------------------------------------------------------------------*/
  495.  
  496.    if (xpubdir == NULL)
  497.        anchor->pubdir = E_pubdir;
  498.    else
  499.        anchor->pubdir = xpubdir;
  500.  
  501. /*--------------------------------------------------------------------*/
  502. /*    If no explicit directories given, give them access to pubdir    */
  503. /*--------------------------------------------------------------------*/
  504.  
  505.    if ( anchor->dirsize == 0)
  506.    {
  507.       max_elements = InitDir( anchor->pubdir, ALLOW_READ, TRUE,
  508.                               anchor, max_elements );
  509.       max_elements = InitDir( anchor->pubdir, ALLOW_WRITE, TRUE,
  510.                               anchor, max_elements );
  511.    }
  512.  
  513.    if ( max_elements == 0 )
  514.       success = FALSE;
  515.    else {
  516.       size_t subscript;
  517.       anchor->dirlist = realloc( anchor->dirlist,
  518.                                  anchor->dirsize * sizeof anchor->dirlist[0]);
  519.       checkref( anchor->dirlist );
  520.       qsort(anchor->dirlist, anchor->dirsize, sizeof(anchor->dirlist[0]),
  521.                dircmp);
  522.       if ( debuglevel > 4 )
  523.       for ( subscript = 0; subscript < anchor->dirsize; subscript++ )
  524.          printmsg(4, "InitEntry: dirlist[%d] %s\t%s\t%s",
  525.                   subscript,
  526.                   anchor->dirlist[subscript].grant ? "grant" : "deny" ,
  527.                   anchor->dirlist[subscript].priv == ALLOW_WRITE ?
  528.                            "WRITE" : "READ" ,
  529.                   anchor->dirlist[subscript].path );
  530.    } /* else */
  531.  
  532. /*--------------------------------------------------------------------*/
  533. /*                          Return to caller                          */
  534. /*--------------------------------------------------------------------*/
  535.  
  536.    return success;
  537.  
  538. } /* InitEntry */
  539.  
  540. /*--------------------------------------------------------------------*/
  541. /*    I n i t D i r                                                   */
  542. /*                                                                    */
  543. /*    Initialize security table directory entries                     */
  544. /*--------------------------------------------------------------------*/
  545.  
  546. static size_t InitDir( char *directories,
  547.          const REMOTE_ACCESS access,
  548.          const boolean grant,
  549.          struct HostSecurity *anchor,
  550.          size_t max_elements )
  551. {
  552.    char *field = directories;
  553.    char *token = directories;
  554.    struct  stat    statbuf;
  555.    size_t subscript;
  556.  
  557. /*--------------------------------------------------------------------*/
  558. /*    Don't process data if no input or we previously had an error    */
  559. /*--------------------------------------------------------------------*/
  560.  
  561.    if ( (directories == NULL ) || ( max_elements == 0) )
  562.       return max_elements;
  563.  
  564. /*--------------------------------------------------------------------*/
  565. /*              Begin loop to process names in the path               */
  566. /*--------------------------------------------------------------------*/
  567.  
  568.    while ( (token = NextField( field )) != NULL)
  569.    {
  570.       char path[FILENAME_MAX];
  571.       if ( anchor->dirsize == max_elements )
  572.       {
  573.          max_elements = max_elements * 2;
  574.          anchor->dirlist = realloc( anchor->dirlist,
  575.                 sizeof anchor->dirlist[0] * max_elements );
  576.          checkref( anchor->dirlist );
  577.       }
  578.  
  579. /*--------------------------------------------------------------------*/
  580. /*                      Normalize directory name                      */
  581. /*--------------------------------------------------------------------*/
  582.  
  583.       strcpy( path, token);
  584.       if (isalpha(path[0]) && (path[1] != ':') && (strlen(path) == 2))
  585.          ;                 /* Yup, do nothing for root drive names  */
  586.       else if ( expand_path( path, ".", E_pubdir , NULL) == NULL )
  587.       {
  588.          printmsg(0, "Unable to expand path \"%s\"",path );
  589.          return 0;
  590.       } /* else */
  591.  
  592.       field = newstr( normalize( path ));
  593.  
  594. /*--------------------------------------------------------------------*/
  595. /*               Verify it really is a valid directory                */
  596. /*--------------------------------------------------------------------*/
  597.  
  598.       if ( strlen( field ) > 2 ) /* More than just drive/colon? (x:) */
  599.       {                       /* Yes --> Go check disk for path      */
  600.          if (stat(field , &statbuf) != 0)
  601.          {
  602.             printerr(field);
  603.             return 0;            /* Path is invalid, give up         */
  604.          }
  605.          else if ((statbuf.st_mode & S_IFDIR) == 0)
  606.          {
  607.             printmsg(0,"InitDir: \"%s\" is a file, not a directory",field);
  608.             return 0;            /* Path is invalid, give up         */
  609.          }
  610.       } /* if ( strlen( field ) > 2 ) */
  611.  
  612. /*--------------------------------------------------------------------*/
  613. /*           Verify this directory not already in the list            */
  614. /*--------------------------------------------------------------------*/
  615.  
  616.       for (subscript = 0; subscript < anchor->dirsize ; subscript++)
  617.       {
  618.          if ( (access == anchor->dirlist[subscript].priv) &&
  619.               equali( field, anchor->dirlist[subscript].path))
  620.          {
  621.             printmsg(0,"InitDir: Duplicate directory %s/", field);
  622.             return 0;
  623.          } /* if */
  624.       } /* for */
  625.  
  626. /*--------------------------------------------------------------------*/
  627. /*            No conflict, add this directory to the list             */
  628. /*--------------------------------------------------------------------*/
  629.  
  630.       printmsg(10,"InitDir: Adding \"%s\" as \"%s\"", token , field);
  631.       anchor->dirlist[subscript].path  = field;
  632.       anchor->dirlist[subscript].priv  = access;
  633.       anchor->dirlist[subscript].grant = grant;
  634.       anchor->dirsize++;
  635.  
  636.       field = NULL;           /* Look at next field next pass        */
  637.  
  638.    } /* while ( (field = NextField( field )) != NULL) */
  639.  
  640. /*--------------------------------------------------------------------*/
  641. /*                          Return to caller                          */
  642. /*--------------------------------------------------------------------*/
  643.  
  644.    return max_elements;
  645. } /* InitDir */
  646.  
  647. /*--------------------------------------------------------------------*/
  648. /*    d i r c m p                                                     */
  649. /*                                                                    */
  650. /*                                                                    */
  651. /*    Compares two directory structures for sorting                   */
  652. /*--------------------------------------------------------------------*/
  653.  
  654. int dircmp( const void *a , const void *b )
  655. {
  656.    struct DIRLIST *x = (struct DIRLIST*) a;
  657.    struct DIRLIST *y = (struct DIRLIST*) b;
  658.  
  659.    int result = strcmp(x->path, y->path);
  660.  
  661.    if (result == 0 && (x->priv != y->priv))
  662.       result = ( x->priv < y->priv ) ? -1 : 1;
  663.  
  664.    return result;
  665. }  /*dircmp*/
  666.  
  667. /*--------------------------------------------------------------------*/
  668. /*    V a l i d a t e H o s t                                         */
  669. /*                                                                    */
  670. /*    Determine that a host is allowed for a specific login           */
  671. /*--------------------------------------------------------------------*/
  672.  
  673. boolean ValidateHost( const char *host )
  674. {
  675.    char **target;
  676.  
  677. /*--------------------------------------------------------------------*/
  678. /*      If this host has no security profile, reject the access       */
  679. /*--------------------------------------------------------------------*/
  680.  
  681.    if ( securep == NULL )
  682.       return FALSE;
  683.  
  684. /*--------------------------------------------------------------------*/
  685. /*    If we allow any host on this user id, use it if the calling     */
  686. /*    host is not supported any other profile                         */
  687. /*--------------------------------------------------------------------*/
  688.  
  689.    target = securep->validate;
  690.    if ( target == NULL )      /* No validate list for this user?     */
  691.    {                          /* Correct --> Use if none for host    */
  692.       struct HostTable *hostp = checkreal( host );
  693.       if ( hostp == BADHOST ) /* Host exist?                         */
  694.          panic();             /* No --> Internal error, abort        */
  695.  
  696.       return hostp->anylogin; /* Allow action if generic access
  697.                                  allowed for host                    */
  698.    }  /* if ( target == NULL ) */
  699.  
  700. /*--------------------------------------------------------------------*/
  701. /*          Determine if this host is allowed for this login          */
  702. /*--------------------------------------------------------------------*/
  703.  
  704.    while (*target != NULL)
  705.    {
  706.       if ( equal(*target++, host ))
  707.          return TRUE;
  708.    } /* (*target != NULL) */
  709.  
  710. /*--------------------------------------------------------------------*/
  711. /*                 We didn't find the host; reject it                 */
  712. /*--------------------------------------------------------------------*/
  713.  
  714.    return FALSE;
  715.  
  716. } /* ValidateHost */
  717.  
  718. /*--------------------------------------------------------------------*/
  719. /*    V a l i d a t e F i l e                                         */
  720. /*                                                                    */
  721. /*    Allow or reject access to a file by name                        */
  722. /*--------------------------------------------------------------------*/
  723.  
  724. boolean ValidateFile( const char *input,  /* Full path name          */
  725.                       const REMOTE_ACCESS needed )
  726. {
  727.    char path[FILENAME_MAX];
  728.    char *column;
  729.  
  730. /*--------------------------------------------------------------------*/
  731. /*                  Validate the length of the name                   */
  732. /*--------------------------------------------------------------------*/
  733.  
  734.    printmsg(5,"ValidateFile: Checking %s access for file \"%s\"",
  735.             (needed == ALLOW_WRITE) ? "WRITE" : "READ" , input);
  736.  
  737.    if ( strlen( input ) >= sizeof path)   /* Reject all invalid names*/
  738.    {
  739.       printmsg(0,"ValidateFile: Access rejected, name too long: %s",
  740.                  input);
  741.       return FALSE;
  742.    }
  743.  
  744. /*--------------------------------------------------------------------*/
  745. /*     Validate format of name; we don't allow parent directories     */
  746. /*--------------------------------------------------------------------*/
  747.  
  748.    if ( strstr( input, "..") )            /* Games with parent dir?  */
  749.    {
  750.       printmsg(0,"ValidateFile: Access rejected, name not normalized: %s",
  751.                  input);
  752.       return FALSE;
  753.    }
  754.  
  755. /*--------------------------------------------------------------------*/
  756. /*                Validate the security table is okay                 */
  757. /*--------------------------------------------------------------------*/
  758.  
  759.    if ( securep == NULL )
  760.       panic();
  761.  
  762. /*--------------------------------------------------------------------*/
  763. /*                        Handle local system                         */
  764. /*--------------------------------------------------------------------*/
  765.  
  766.    if ( securep->local )      /* Local system?                       */
  767.       return TRUE;            /* Yes --> Bless the request           */
  768.  
  769. /*--------------------------------------------------------------------*/
  770. /*       Determine if the user is allowed to request files            */
  771. /*--------------------------------------------------------------------*/
  772.  
  773.    if ((needed == ALLOW_READ) && !securep->request)
  774.    {
  775.       printmsg(0,"ValidateFile: access rejected, "
  776.                  "REQUEST not enabled in permissions file");
  777.       return FALSE;
  778.    }
  779.  
  780. /*--------------------------------------------------------------------*/
  781. /*                           Copy path name                           */
  782. /*--------------------------------------------------------------------*/
  783.  
  784.    if ( input[1] == ':' )
  785.       strcpy( path, input );
  786.    else
  787.       strcat( strcpy( path , drive ), input );
  788.    strlwr( path );
  789.  
  790. /*--------------------------------------------------------------------*/
  791. /*              Locate the best file match for the path               */
  792. /*--------------------------------------------------------------------*/
  793.  
  794.    while( (column = strrchr( path, '/')) != NULL )
  795.    {
  796.       int lower = 0;
  797.       int upper = securep->dirsize - 1;
  798.  
  799.       *column = '\0';
  800.       printmsg(10,"ValidateFile: Searching for %s", path);
  801.  
  802.       while( lower <= upper )
  803.       {
  804.          int midpoint = (lower + upper) / 2;
  805.          int hit = strcmp(path, securep->dirlist[midpoint].path);
  806.  
  807.          printmsg(10,"ValidateFile: Comparing %s and %s",
  808.                         path, securep->dirlist[midpoint].path);
  809.  
  810.          if ( hit == 0 )
  811.             hit = (int) needed - (int) securep->dirlist[midpoint].priv;
  812.  
  813.          if (hit > 0)
  814.             lower = midpoint + 1;
  815.          else if (hit < 0)
  816.             upper = midpoint - 1;
  817.          else {
  818.             printmsg( securep->dirlist[midpoint].grant ? 5 : 0 ,
  819.                      "ValidateFile: Found path \"%s\", access %s to \"%s\"",
  820.                      securep->dirlist[midpoint].path,
  821.                      securep->dirlist[midpoint].grant ?
  822.                                     "granted" : "denied", input);
  823.             return securep->dirlist[midpoint].grant;
  824.          }
  825.       } /* while( lower <= upper ) */
  826.    } /* while( (column = strrchr( path, '/')) != NULL ) */
  827.  
  828. /*--------------------------------------------------------------------*/
  829. /*          We didn't find the file; reject all access to it          */
  830. /*--------------------------------------------------------------------*/
  831.  
  832.    printmsg(0,"ValidateFile: No access definition found for \
  833. \"%s\", access denied",
  834.             input);
  835.    return FALSE;
  836.  
  837. } /* ValidateFile */
  838.  
  839.  
  840. /*--------------------------------------------------------------------*/
  841. /*    G e t S e c u r i t y                                           */
  842. /*                                                                    */
  843. /*    Return security structure for to use when calling out to        */
  844. /*    another system                                                  */
  845. /*--------------------------------------------------------------------*/
  846.  
  847. struct HostSecurity *GetSecurity( struct HostTable *hostp)
  848. {
  849.    if ((hostp->hsecure == NULL) && (default_security != NULL ))
  850.    {
  851.       printmsg(2,"GetSecurity: Using security for MACHINE=OTHER for \
  852. system \"%s\"", hostp->hostname );
  853.       hostp->hsecure = default_security;
  854.    } /* if  */
  855.  
  856.    return hostp->hsecure;
  857.  
  858. } /* GetSecurity */
  859.